其他
不懂别瞎搞!Redis 性能优化的 13 条军规!
The following article is from Java中文社群 Author 老王
缩短键值对的存储长度; 使用 lazy free(延迟删除)特性; 设置键值的过期时间; 禁用长耗时的查询命令; 使用 slowlog 优化耗时命令; 使用 Pipeline 批量操作数据; 避免大量数据同时失效; 客户端使用优化; 限制 Redis 内存大小; 使用物理机而非虚拟机安装 Redis 服务; 检查数据持久化策略; 禁用 THP 特性; 使用分布式架构来增加读写速度。
1.缩短键值对的存储长度
内容越大需要的持久化时间就越长,需要挂起的时间越长,Redis 的性能就会越低; 内容越大在网络上传输的内容就越多,需要的时间就越长,整体的运行速度就越低; 内容越大占用的内存就越多,就会更频繁的触发内存淘汰机制,从而给 Redis 带来了更多的运行负担。
2.使用 lazy free 特性
lazyfree-lazy-expire no
lazyfree-lazy-server-del no
slave-lazy-flush no
lazyfree-lazy-eviction:表示当 Redis 运行内存超过 maxmeory 时,是否开启 lazy free 机制删除; lazyfree-lazy-expire:表示设置了过期时间的键值,当过期之后是否开启 lazy free 机制删除; lazyfree-lazy-server-del:有些指令在处理已存在的键时,会带有一个隐式的 del 键的操作,比如 rename 命令,当目标键已存在,Redis 会先删除目标键,如果这些目标键是一个 big key,就会造成阻塞删除的问题,此配置表示在这种场景中是否开启 lazy free 机制删除; slave-lazy-flush:针对 slave(从节点) 进行全量数据同步,slave 在加载 master 的 RDB 文件前,会运行 flushall 来清理自己的数据,它表示此时是否开启 lazy free 机制删除。
3.设置键值的过期时间
4.禁用长耗时的查询命令
决定禁止使用 keys 命令; 避免一次查询所有的成员,要使用 scan 命令进行分批的,游标式的遍历; 通过机制严格控制 Hash、Set、Sorted Set 等结构的数据大小; 将排序、并集、交集等操作放在客户端执行,以减少 Redis 服务器运行压力; 删除 (del) 一个大数据的时候,可能会需要很长时间,所以建议用异步删除的方式 unlink,它会启动一个新的线程来删除目标数据,而不阻塞 Redis 的主线程。
5.使用 slowlog 优化耗时命令
slowlog-log-slower-than
:用于设置慢查询的评定时间,也就是说超过此配置项的命令,将会被当成慢操作记录在慢查询日志中,它执行单位是微秒 (1 秒等于 1000000 微秒);slowlog-max-len
:用来配置慢查询日志的最大记录数。
slowlog get n
来获取相关的慢查询日志,再找到这些慢查询对应的业务进行相关的优化。6.使用 Pipeline 批量操作数据
public static void main(String[] args) {
Jedis jedis = new Jedis("127.0.0.1", 6379);
// 记录执行开始时间
long beginTime = System.currentTimeMillis();
// 获取 Pipeline 对象
Pipeline pipe = jedis.pipelined();
// 设置多个 Redis 命令
for (int i = 0; i < 100; i++) {
pipe.set("key" + i, "val" + i);
pipe.del("key"+i);
}
// 执行命令
pipe.sync();
// 记录执行结束时间
long endTime = System.currentTimeMillis();
System.out.println("执行耗时:" + (endTime - beginTime) + "毫秒");
}
}
执行耗时:297毫秒
public static void main(String[] args) {
Jedis jedis = new Jedis("127.0.0.1", 6379);
// 记录执行开始时间
long beginTime = System.currentTimeMillis();
for (int i = 0; i < 100; i++) {
jedis.set("key" + i, "val" + i);
jedis.del("key"+i);
}
// 记录执行结束时间
long endTime = System.currentTimeMillis();
System.out.println("执行耗时:" + (endTime - beginTime) + "毫秒");
}
}
执行耗时:17276毫秒
7.避免大量数据同时失效
hz 10
,Redis 会随机抽取 20 个值,删除这 20 个键中过期的键,如果过期 key 的比例超过 25% ,重复执行此流程,如下图所示:8.客户端使用优化
9.限制 Redis 内存大小
maxmemory <bytes>
是被注释掉的,这样就会导致在物理内存不足时,使用 swap 空间既交换空间,而当操心系统将 Redis 所用的内存分页移至 swap 空间时,将会阻塞 Redis 进程,导致 Redis 出现延迟,从而影响 Redis 的整体性能。因此我们需要限制 Redis 的内存大小为一个固定的值,当 Redis 的运行到达此值时会触发内存淘汰策略,内存淘汰策略在 Redis 4.0 之后有 8 种:noeviction:不淘汰任何数据,当内存不足时,新增操作会报错,Redis 默认内存淘汰策略; allkeys-lru:淘汰整个键值中最久未使用的键值; allkeys-random:随机淘汰任意键值; volatile-lru:淘汰所有设置了过期时间的键值中最久未使用的键值; volatile-random:随机淘汰设置了过期时间的任意键值; volatile-ttl:优先淘汰更早过期的键值。
volatile-lfu:淘汰所有设置了过期时间的键值中,最少使用的键值; allkeys-lfu:淘汰整个键值中最少使用的键值。
10.使用物理机而非虚拟机
./redis-cli --intrinsic-latency 100
命令查看延迟时间,如果对 Redis 的性能有较高要求的话,应尽可能在物理机上直接部署 Redis 服务器。11.检查数据持久化策略
RDB(Redis DataBase,快照方式)将某一个时刻的内存数据,以二进制的方式写入磁盘; AOF(Append Only File,文件追加方式),记录所有的操作命令,并以文本的形式追加到文件中; 混合持久化方式,Redis 4.0 之后新增的方式,混合持久化是结合了 RDB 和 AOF 的优点,在写入的时候,先把当前的数据以 RDB 的形式写入文件的开头,再将后续的操作命令以 AOF 的格式存入文件,这样既能保证 Redis 重启时的速度,又能减低数据丢失的风险。
config get aof-use-rdb-preamble
命令,执行结果如下图所示:通过命令行开启 通过修改 Redis 配置文件开启
① 通过命令行开启
config set aof-use-rdb-preamble yes
执行结果如下图所示:② 通过修改 Redis 配置文件开启
aof-use-rdb-preamble no
改为 aof-use-rdb-preamble yes
如下图所示:12.禁用 THP 特性
echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo never > /sys/kernel/mm/transparent_hugepage/enabled
。13.使用分布式架构来增加读写速度
主从同步 哨兵模式 Redis Cluster 集群
往期推荐
Java 14 发布了,不使用"class"也能定义类了?还顺手要干掉Lombok!
太赞了:《Effective Java 第三版》最新中文版开放下载!
【盘它!】那些让效率MAX的工具和方法(Mac篇)
你还不了解Redis的发布/订阅功能与Redis的Stream吗
有道无术,术可成;有术无道,止于术
欢迎大家关注Java之道公众号
好文章,我在看❤️